# 函数
def add_num():
    resu=1+2
    print(resu)

add_num()

def add_num(a,b):
    resu=a+b
    print(resu)
add_num(8,3)

# 函数的返回值作用

def sum_num(a,b):
    return a+b
retu=sum_num(2,4)
print(retu)

# 定义函数的说明文档  help
def sum_num(a,b):
    return a+b
help(sum_num)

# 所谓函数嵌套调用指的是一个函数里面又调用了另外一个函数
def testb():
    print("----1")

def testa():
    print("....2")
    testb()
    print("---3")
testa()

# 打印一条横线
def print1():
    print("-----"* 10)

print1()

# 打印多条横线
def print1():
    print("--"* 10)

def print2(num):
    i =0
    while i <num:
        print1()
        i+=1

print2(5)

#  求三个数之和
def sum_num(a,b,c):
    return a+b+c

resu =sum_num(1,2,3)
print(resu)

# 求三个数平均值
def ave(a,b,c):
    sum =sum_num(a,b,c)
    return sum / 3
re=ave(1,2,3)
print(re)


# 局部变量
def test1():
    a=100
    print(a)
test1()
# print(a)  #报错

# 全局变量
a=100
def test1():
    print(a)

def testb():
    print(a)
test1()
testb()

#  testB函数需求修改变量a的值为200, 如何修改程序?
a=100
def test1():
    print(a)

def testb():
    a=200
    print(a)
test1()
testb()

# # global 关键字声明a是全局变量
a=100
def test1():
    print(a)

def testb():
    global a
    a=200
    print(a)

test1()
testb()


# 位置参数: 调用函数时根据函数定义的参数位置来传递参数。
def user(name,age,gender):
    print(f'名字是{name},年龄是{age},性别是{gender}')
user('wq',18,'女')


# 关键字参数
def user(name,age,gender):
    print(f'您的名字是{name},年龄是{age},性别是{gender}')

user('wq',age=18,gender='女')
# 注意:函数调用时,如果有位置参数时, 位置参数必须在关键字参数的前面, 但关键字参数之间不存在先后
# 顺序。
# 缺省参数
def user(name,age,gender='男'):
    print(f'您的名字是{name},年龄是{age},性别是{gender}')
user('wq',18)


# 不定长参数也叫可变参数。用于不确定调用的时候会传递多少个参数(不传参也可以)的场景。此时,可用
# 包裹(packing)位置参数, 或者包裹关键字参数, 来进行参数传递, 会显得非常方便。
def user(*args):
    print(args)

user('wq')
user('wq',1)
list1=[1,2,3,4]
user(*list1)
# 注意: 传进的所有参数都会被args变量收集, 它会根据传进参数的位置合并为一个元组(tuple),
# args是元组类型, 这就是包裹位置传递。

# 包裹关键字传递
def user(**kwargs):
    print(kwargs)

user(name='wq')
user(name='wq',age=18)
dict1={'name':'wq','age':18}
user(**dict1)


# 拆包: 元组
def retu():
    return 100,200
num1,num2=retu()
print(num1)
print(num2)

# 拆包: 字典
dict1={'name':'wq','age':18}
a,b=dict1
#  对字典进行拆包，取出来的是字典的key
print(a)
print(b)
#  对字典的值进行拆包，取出来的是字典的value
print(dict1[a])
print(dict1[b])

# 引用
#  int类型
a=1
b=a
print(id(a))
print(id(b))

# 列表
aa=[10,20]
bb=aa
print(id(aa))
print(id(bb))


# 所谓可变类型与不可变类型是指: 数据能够直接进行修改, 如果能直接修改那么就是可变, 否则是不可变。
# 可变类型
# 列表
# 字典
# 集合
# 不可变类型
# 整型
# 浮点型
# 字符串
# 元组


# 打开文件
# name:是要打开的目标文件名的字符串(可以包含文件所在的具体路径)
# mode︰设置打开文件的模式(访问模式):只读、写入、追加等。
# encoding : 打开文件的字符编码格式。

# 1. 打开文件 f = open('test.txt', 'w')
# 2.文件写入 f.write('hello world')
# 3. 关闭文件 f.close()

# 1. w和a模式: 如果文件不存在则创建该文件; 如果文件存在, w模式先清空再写入, a模式直接末
# 尾追加。
# 2. r模式: 如果文件不存在则报错。

# 读
# 文件对象.read(num)
# readlines可以按照行的方式把整个文件中的内容进行一次性读取，并且返回的是一个列表，其中每一行
# 的数据为一个元素。
# readline()一次读取一行内容。
#  seek()  作用: 用来移动文件指针。
# tell() 作用: 用来查看文件指针位置。
# 导入os模块  import os
# os.函数名()
# os.rename(目标文件名,新文件名)   文件重命名
# os.remove(目标文件名)  删除
# os.mkdir(文件夹名字) 创建文件夹
# os.rmdir(文件夹名字) 删除文件夹
# os.getcwd() 获取当前目录
# os.chdir(目录)  改变默认目录
# os.listdir(目录)   获取目录列表
# s.path.dirname( __file__ ):查看当前文件所属目录


# 递归
#  3以内数字累加和
def sum(num):
    if num==1:
        return 1
    return num +sum(num-1)

res =sum(3)
print(res)

# lambda的参数形式
# 无参数
fum1=lambda :100
print(fum1())

# 一个参数
fum2=lambda a:a
print(fum2('hello word'))

# 默认参数
fum3=lambda a,b,c=100:a+b+c
print(fum3(10,20))

# 可变参数: *args
fum4=lambda *args:args
print(fum4(1,2,3))

# 可变参数: **kwargs
fum5=lambda **kwargs:kwargs
print(fum5(name='wq',age=18))

#  带判断的lambda
fu1=lambda a,b:a if a>b else b
print(fu1(100,400))

# 列表数据按字典key的值排序
students = [ {'name': 'TOM', 'age': 20},
             {'name': 'ROSE', 'age': 19},
             {'name': 'Jack', 'age': 22} ]
#按name值升序排列
students.sort(key=lambda x:x['name'])
print(students)

# 按name值降序排列
students.sort(key=lambda x:x['name'],reverse=True)
print(students)

# 按age值升序排列
students.sort(key=lambda x:x['age'])
print(students)


# abs()函数可以完成对数字求绝对值计算。
#  任意两个数字, 按照指定要求整理数字后在进行求和计算
def add(a,b):
    return abs(a)+abs(b)
res=add(-1,4)
print(res)

def sum(a,b,f):
    return f(a)+f(b)
res=sum(-2,2,abs)
print(res)
# 注意:两种方法对比后,发现, 方法2的代码会更加简洁, 函数灵活性更高。

# 内置高阶函数

# map(func, lst)，将传入的函数变量func作用到lst变量的每个元素中，并将结果组成新的列表(Python2)/
# 迭代器(Python3)返回。
# 计算list1序列中各个数字的2次方
list1=[1,2,3,4,5]
def fun(x):
    return  x **2
res=map(fun,list1)
print(res)
print(list(res))

# reduce(func，Ilst)，其中func必须有两个参数。每次func计算的结果继续和序列的下一个元素做累积计
# 算。
# 计算list1序列中各个数字的累加和。
import functools
list1=[1,2,3,4]
def fun(a,b):
    return a+b
res=functools.reduce(fun,list1)
print(res)

# filter(func, Ilst)函数用于过滤序列,过滤掉不符合条件的元素,返回一个filter对象。如果要转换为列表,可以
# 使用list()来转换。
list1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
def fun1(x):
    return x% 2==0
res=filter(fun1,list1)
print(res)
print(list(res))
